package com.motu.monstercity.server.game.web;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message.Builder;
import com.googlecode.protobuf.format.JsonFormat;
import com.motu.monstercity.protocol.CmdEnum;
import com.motu.monstercity.protocol.CmdEnum.EnumCmdID;
import com.motu.monstercity.server.game.verticle.MainVerticle;
import com.motu.vertx.module.utility.clickhouse.ClickhouseTool;
import com.motu.vertx.module.utility.mysql.MysqlClient;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import com.motu.vertx.module.utility.webtool.BaseWebHandler;
import com.motu.vertx.module.utility.webtool.SearchCondition;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.client.WebClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

public class ProtocolmonitorHandler extends BaseWebHandler {
	private static final Logger logger = LoggerFactory.getLogger(ProtocolmonitorHandler.class);

	private static JsonObject config;
	private static String database = "";
	private static String tableNameData = "protocol_monitor_data";

	public static void init(JsonObject appConfig){
		config = appConfig;
		JsonObject jsonConfig = appConfig.getJsonObject("housepower-clickhouse");
		database = jsonConfig.getString("database");
	}

	public static void add(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		addToTable(routingContext, MysqlClient.getServerPool(), "protocol_monitor", json);
	}

	public static void update(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		updateToTable(routingContext, MysqlClient.getServerPool(), "protocol_monitor", json);
	}

	public static void getone(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		getFromTable(routingContext, MysqlClient.getServerPool(), "protocol_monitor");

	}

	public static void delete(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		deleteFromTable(routingContext, MysqlClient.getServerPool(), "protocol_monitor");
	}

	public static void search(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		List<SearchCondition> scList = new ArrayList<SearchCondition>();
		scList.add(new SearchCondition("cmd_code", "=", null, null));
		searchFromTable(routingContext, MysqlClient.getServerPool(), json, "protocol_monitor", scList);
	}


	/**
	 *
	 */
	public static void search_data_clickhouse(RoutingContext routingContext,JsonObject json,String adminName,WebClient client){
		HttpServerResponse response = routingContext.response();
		JsonArray params1 = new JsonArray();
		String whereStr = "";
		logger.info("search_data_clickhouse params: " + json.encode());
		if (json.containsKey("cmdcode")) {
			whereStr += " and cmdcode =? ";
			params1.add(json.getInteger("cmdcode"));
		}
		if (json.containsKey("rescode")) {
			whereStr += " and rescode =? ";
			params1.add(json.getInteger("rescode"));
		}
		if (json.containsKey("userid")) {
			whereStr += " and userid =? ";
			params1.add(json.getLong("userid"));
		}
		if (json.containsKey("stime")) {
			whereStr += " and atime >= timestamp '" + json.getString("stime") + "' ";
		}
		if (json.containsKey("etime")) {
			whereStr += " and atime <= timestamp '" + json.getString("etime") + "' ";
		}

		String sql1 = "select count(1) as total from " + database + "." + tableNameData + " where 1=1 " + whereStr + ";";
		String sql2 = "select * from " + database + "." + tableNameData + " where 1=1 " + whereStr + " order by addtime desc limit ?, ?;";
		JsonArray params2 = params1.copy();
		int pageNo = json.getInteger("pageNo");
		int pageSize = json.getInteger("pageSize");
		int start = pageNo * pageSize;
		params2.add(start);
		params2.add(pageSize);

		Connection clickhouseConnection = ClickhouseTool.initConnection(config);
		if(clickhouseConnection != null) {
			try {
				JsonObject result = new JsonObject();
				JsonArray totalResult = ClickhouseTool.queryJsonArrayFromDb(clickhouseConnection, sql1, params1);
				result.put("total", totalResult.getJsonObject(0).getValue("total"));
				JsonArray searchResult = ClickhouseTool.queryJsonArrayFromDb(clickhouseConnection, sql2, params2);
				JsonArray list = getJsonStrListByClickhouse(searchResult);  //解析为json字符串
				result.put("rows",list);
				sendHttpResponse(routingContext.response(), result);
			} catch (SQLException e) {
				e.printStackTrace();
			}finally {
				try {
					clickhouseConnection.close();//最后关闭连接
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void search_data(RoutingContext routingContext, JsonObject json, String adminName, WebClient client) {
		HttpServerResponse response = routingContext.response();
		JsonArray params1 = new JsonArray();
		String whereStr = "";
		if (json.containsKey("cmdcode")) {
			whereStr += " and cmdcode =? ";
			params1.add(json.getInteger("cmdcode"));
		}
		if (json.containsKey("rescode")) {
			whereStr += " and rescode =? ";
			params1.add(json.getInteger("rescode"));
		}
		if (json.containsKey("userid")) {
			whereStr += " and userid =? ";
			params1.add(json.getLong("userid"));
		}
		if (json.containsKey("stime")) {
			whereStr += " and addtime >= ? ";
			params1.add(TimeUtils.getTimeStrIntValue(json.getString("stime")));
		}
		if (json.containsKey("etime")) {
			whereStr += " and addtime <= ? ";
			params1.add(TimeUtils.getTimeStrIntValue(json.getString("etime")));
		}

		String sql1 = "select count(1) as total from protocol_monitor_data where 1=1 " + whereStr + ";";
		String sql2 = "select * from protocol_monitor_data where 1=1 " + whereStr + " order by addtime desc limit ?, ?;";
		JsonArray params2 = params1.copy();
		int pageNo = json.getInteger("pageNo");
		int pageSize = json.getInteger("pageSize");
		int start = pageNo * pageSize;
		params2.add(start);
		params2.add(pageSize);

		Future<JsonArray> fut1 = MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql1, params1);
		Future<JsonArray> fut2 = MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql2, params2);
		CompositeFuture.all(fut1, fut2).onComplete(res -> {
			if (res.succeeded()) {
				JsonObject result = new JsonObject();
				int total = fut1.result().getJsonObject(0).getInteger("total");
				result.put("total", total);
				JsonArray list = fut2.result();
				JsonArray list2 = getJsonStrList(list);  //解析为json字符串
				result.put("rows", list2);
				sendHttpResponse(response, result);
			} else {
				sendHttpResponseError(response, res.cause().getMessage());
			}
		});
	}

	private static JsonArray getJsonStrList(JsonArray list) {
		JsonArray result = new JsonArray();
		for (int i = 0; i < list.size(); i++) {
			JsonObject obj = list.getJsonObject(i);
			JsonObject tmp = new JsonObject();
			tmp.put("id", obj.getLong("id"));
			tmp.put("userid", obj.getLong("userid"));
			tmp.put("cmdcode", obj.getInteger("cmdcode"));
			tmp.put("request", parseToJsonRequest(obj));
			tmp.put("rescode", obj.getInteger("rescode"));
			tmp.put("response", parseToJsonResponse(obj));
			tmp.put("addtime", obj.getInteger("addtime"));
			result.add(tmp);
		}

		return result;
	}

	/**
	 * 解析为json字符串 request
	 * @param obj
	 * @return
	 */
	private static String parseToJsonRequest(JsonObject obj) {
		int cmdCode = obj.getInteger("cmdcode");
		byte[] requestData = Base64.getDecoder().decode(obj.getBinary("request"));
		String requestJson = "{}";
		try {
			if (cmdCode > 0 && requestData.length > 0) {
				EnumCmdID eId1 = CmdEnum.EnumCmdID.forNumber(cmdCode);
				String cmdName1 = eId1.name();
				Builder res_build1 = ProtobufManager.getRequestBuild(cmdName1, 0);
				res_build1.mergeFrom(requestData);
				requestJson = JsonFormat.printToString(res_build1.build());
			}
		} catch (InvalidProtocolBufferException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return requestJson;
	}


	/**
	 * 解析为json字符串 response
	 * @param obj
	 * @return
	 */
	private static String parseToJsonResponse(JsonObject obj) {
		int resCode = obj.getInteger("rescode");
		byte[] responseData = Base64.getDecoder().decode(obj.getBinary("response"));
		String responseJson = "{}";
		try {
			if (resCode > 0 && responseData.length > 0) {
				EnumCmdID eId2 = CmdEnum.EnumCmdID.forNumber(resCode);
				String cmdName2 = eId2.name();
				Builder res_build2 = ProtobufManager.getResponseBuild(cmdName2, 0);
				res_build2.mergeFrom(responseData);
				responseJson = JsonFormat.printToString(res_build2.build());
			}
		} catch (InvalidProtocolBufferException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return responseJson;
	}


	private static JsonArray getJsonStrListByClickhouse(JsonArray list) {
		JsonArray result = new JsonArray();
		for (int i = 0; i < list.size(); i++) {
			JsonObject obj = list.getJsonObject(i);
			JsonObject tmp = new JsonObject();
			tmp.put("id", obj.getLong("id"));
			tmp.put("userid", obj.getLong("userid"));
			tmp.put("cmdcode", obj.getInteger("cmdcode"));
			tmp.put("request", parseToJsonRequestByClickhouse(obj));
			tmp.put("rescode", obj.getInteger("rescode"));
			tmp.put("response", parseToJsonResponseByClickhouse(obj));
			tmp.put("addtime", obj.getValue("addtime"));
			result.add(tmp);
		}

		return result;
	}

	/**
	 * 解析为json字符串 request
	 * @param obj
	 * @return
	 */
	private static String parseToJsonRequestByClickhouse(JsonObject obj) {
		int cmdCode = obj.getInteger("cmdcode");
		byte[] requestData = Base64.getDecoder().decode(obj.getString("request").getBytes());
		String requestJson = "{}";
		try {
			if (cmdCode > 0 && requestData.length > 0) {
				EnumCmdID eId1 = CmdEnum.EnumCmdID.forNumber(cmdCode);
				String cmdName1 = eId1.name();
				Builder res_build1 = ProtobufManager.getRequestBuild(cmdName1, 0);
				res_build1.mergeFrom(requestData);
				requestJson = JsonFormat.printToString(res_build1.build());
			}
		} catch (InvalidProtocolBufferException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return requestJson;
	}

	/**
	 * 解析为json字符串 response
	 * @param obj
	 * @return
	 */
	private static String parseToJsonResponseByClickhouse(JsonObject obj) {
		int resCode = obj.getInteger("rescode");
		byte[] responseData = Base64.getUrlDecoder().decode(obj.getString("response").getBytes());
		String responseJson = "{}";
		try {
			if (resCode > 0 && responseData.length > 0) {
				EnumCmdID eId2 = CmdEnum.EnumCmdID.forNumber(resCode);
				String cmdName2 = eId2.name();
				Builder res_build2 = ProtobufManager.getResponseBuild(cmdName2, 0);
				res_build2.mergeFrom(responseData);
				responseJson = JsonFormat.printToString(res_build2.build());
			}
		} catch (InvalidProtocolBufferException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return responseJson;
	}
}